use std::error::Error;
use std::{env, fs};

pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
    // let config_bak = config.clone();
    // dbg!(config);
    let content = fs::read_to_string(config.path).expect("Should have been able to read the file");

    // println!("content: {content}");

    let res = iterator_search(&config.query, &content, config.ignore_case);
    // 查找字符串
    if res.is_empty() {
        println!("Not found!");
    } else {
        println!("Found! ! ! !");
        for item in res {
            println!("item: {}", item);
        }
    }

    Ok(())
}


// 查询字符串使用迭代器，简化代码
pub fn iterator_search<'a>(query: &str, content: &'a str, ignore_case: bool) -> Vec<&'a str> {
    let mut query = String::from(query);
    if ignore_case {
        // 转换为小写
        query = query.to_lowercase();
    }

    content.lines().filter(|line| line.contains(&query)).collect()
}


// 查询字符串
pub fn search<'a>(query: &str, content: &'a str, ignore_case: bool) -> Vec<&'a str> {
    let mut result = Vec::new();

    let mut query = String::from(query);
    if ignore_case {
        // 转换为小写
        query = query.to_lowercase();
    }

    for line in content.lines() {
        if line.contains(&query) {
            result.push(line);
        }
    }
    result
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Config {
    pub query: String,
    pub path: String,
    pub ignore_case: bool,
}

impl Config {
    pub fn build_by_iterator(mut args: impl Iterator<Item=String>) -> Result<Config, &'static str> {

        // 第一个参数是程序名 由于无需使用 因此这里直接空调用一次
        args.next();

        let query = match args.next() {
            Some(arg) => arg,
            None => return Err("Didn't get a query string"),
        };

        let path = match args.next() {
            Some(arg) => arg,
            None => return Err("Didn't get a file path"),
        };

        let ignore_case = env::var("IGNORE_CASE").is_ok();

        // 返回内容
        Ok(Config { query, path, ignore_case })
    }

    pub fn build_by_vec(args: &Vec<String>) -> Result<Config, &str> {
        if args.len() < 3 {
            return Err("Usage: {} <query> <path>");
        }
        parse_config(args)
        // 查询的字符串
        // let query = String::from(&args[1]);
        // // 查询文件的路径
        // let path = String::from(&args[2]);
        //
        // Config { query, path }
    }
}


fn parse_config(args: &[String]) -> Result<Config, &str> {
    // 查询的字符串
    // let query = String::from(&args[1]);
    let query = args[1].clone();
    // 查询文件的路径
    let path = args[2].clone();

    let ignore_case = env::var("IGNORE_CASE").is_ok();

    Ok(Config { query, path, ignore_case })
}


#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_config() {
        let args: Vec<String> = vec!["program".to_string(), "query".to_string(), "path/to/file".to_string()];
        let expected = Config {
            query: "query".to_string(),
            path: "path/to/file".to_string(),
            ignore_case: false,
        };

        assert_eq!(expected, Config::build(&args).unwrap());
    }

    #[test]
    fn test_search() {
        let content = r##"hello world!
get world
        goster"##;
        let query = "World";
        assert_eq!(vec!["hello world!", "get world"], search(&query, &content, true));
    }
}